package form.ui.Effect
{
	import flash.events.TimerEvent;
	import flash.utils.getTimer;
	
	import form.events.InterpolationEvent;
	import form.events.InterpolationEventType;
	import form.ui.Effect;

	/** 
	 * The Interpolate class is a base class used by Effects involving interpolation.
	 */	
	public class Interpolate extends Effect 
	{
		private var _duration:Number = 0;
		private var _loop:Boolean = false;
		
		private var _v0:Number = 0;
		private var _v1:Number = 1;
		
		private var _v:Number;
		private var __t:Number = 0;
		
		public function Interpolate() { 
			super(); 
			this.eval();
		}
		
		public function get duration():Number { return this._duration / 1000; }
		public function set duration(value:Number):void { this._duration = Math.max(value, 0) * 1000; }
		
		public function get loop():Boolean { return this._loop; }
		public function set loop(value:Boolean):void { this._loop = value; }
		
		public function get startValue():Number { return this.v0; }
		public function set startValue(value:Number):void { this.v0 = value; }
		
		public function get stopValue():Number { return this.v1; }
		public function set stopValue(value:Number):void { this.v1 = value; }
		
		public function  get value():Number { return this.v; }
				
		protected function get v0():Number { return this._v0; }
		protected function set v0(value:Number):void { 
			this._v0 = value; 
			this.eval();
		}
		
		protected function get v1():Number { return this._v1; }
		protected function set v1(value:Number):void { 
			this._v1 = value; 
			this.eval();
		}
		
		protected function get v():Number { return this._v; } 
		
		protected function get t():Number { return this._t; }
		
		private function get _t():Number { return this.__t; }
		private function set _t(value:Number):void { 
			this.__t = value;
			
			this._v = this.v0 + this.t * (this.v1 - this.v0);
		}
	
		public override function start():void {
			this._t = 0;
			super.start();
			
			var start:InterpolationEvent = new InterpolationEvent(InterpolationEventType.START);
			start.value = this.v;
			this.dispatchEvent(start);
			
			var change:InterpolationEvent = new InterpolationEvent(InterpolationEventType.CHANGE);
			change.value = this.v;
			this.dispatchEvent(change);
		}
		
		public override function stop():void {
			super.stop();
			
			var stop:InterpolationEvent = new InterpolationEvent(InterpolationEventType.STOP);
			stop.value = this.v;
			this.dispatchEvent(stop);
		}
		
		public override function reset():void {
			this._t = 0;
			
			var change:InterpolationEvent = new InterpolationEvent(InterpolationEventType.CHANGE);
			change.value = this.v;
			this.dispatchEvent(change);
			
			super.reset();
		}
		
		protected override function onTimer(event:TimerEvent):void {
			var current:uint = getTimer();
			var elapsed:Number = current - this.startTime;
			this._t = this._duration == 0 ? 1 : Math.min(elapsed / this._duration, 1);
			
			super.onTimer(event);
			
			if (this.t >= 1) { 
				if (this.loop) {
					this.startTime = current;
					this._t = 0; 
				} else { this.timer.stop(); } 
			}
			
			var change:InterpolationEvent = new InterpolationEvent(InterpolationEventType.CHANGE);
			change.value = this.v;
			this.dispatchEvent(change);
			
			if (!this.timer.running) {
				var stop:InterpolationEvent = new InterpolationEvent(InterpolationEventType.STOP);
				stop.value = this.v;
				this.dispatchEvent(stop);
			}
		}
		
		private function eval():void { this._t = this.t; }
	}
}